/**
 * 画箭头
 * @param {*} fromX
 * @param {*} fromY
 * @param {*} toX
 * @param {*} toY
 * @param {*} theta
 * @param {*} headlen
 * @param {*} width
 * @param {*} color
 */

let index = 1;
class DrawArrow {
	constructor(props) {
		this.id = `DrawArrow_${index++}`;
		this.type = 'DrawArrow';
		this.props = props;
		this.render = this.render.bind(this);
		this.computePath = this.computePath.bind(this);
		const canvas = document.getElementById("canvas");
		this.ctx = canvas.getContext("2d");
		const { fromX, fromY, toX, toY } = this.props;
		this.fromX = fromX;
		this.fromY = fromY;
		this.toX = toX;
		this.toY = toY;
		this.width = 100;
		this.height = 100;
		this.startElement = null;
		this.endElement = null;
		this.direction = 0; // 箭头初始方向， 0 1 2 3 ： 上 右 下 左
	}
	render() {
		let step = 30;
		this.ctx.moveTo(this.fromX, this.fromY);
		this.computePath(this.fromX, this.fromY, 1, this.direction);
	}
	drug(x1, y1, x2, y2) {
		this.fromX = x1 || this.fromX;
		this.fromY = y1 || this.fromY;
		this.toX = x2 || this.toX;
		this.toY = y2 || this.toY;
	}
	/**
	 * 递归路线计算
	 * @param {*} x1
	 * @param {*} y1
	 * @param {*} x2
	 * @param {*} y2
	 * @param {*} index
	 */
	computePath(x, y, index, direction) {
		function obliqueX() {
			let x3 = x, y3 = y + (this.toY - y) / 2;
			this.ctx.lineTo(x3, y3);
			x1 = this.toX
			y1 = y3;
			this.ctx.stroke();
		}

		function obliqueY() {
			let x3 = x + (this.toX - x) / 2, y3 = y;
			this.ctx.lineTo(x3, y3);
			x1 = x3
			y1 = this.toY;
			this.ctx.stroke();
		}
		index++;
		if (x === this.toX && y === this.toY) return;
		// console.log("第几次递归：", index++);
		if (index > 5) {
			console.log("算法异常");
			return false;
		}
		let rato = (this.toY - y) / (this.toX - x);
		let x1, y1;
		let next = () => {
			this.ctx.lineTo(x1, y1);
			this.ctx.stroke();
			this.drawArrow(x1, y1, this.toX, this.toY);
		};
		let repeat = (x, y) => {
			this.ctx.lineTo(x, y);
			this.ctx.stroke();
			this.computePath(x, y, index, direction);
		};
		// 上
		if (direction === 0) {
			if (this.toY <= y) {
				// 判断修改箭头方向
				if (Math.abs(this.toY - y) > Math.abs(this.toX - x)) {
					obliqueX.call(this)
				} else {
					x1 = x;
					y1 = this.toY;

				}
				next();
			} else {
				let offset =
					index === 2 ? this.width / 2 + 30 : this.height + 60;
				offset = index <= 3 ? offset : 0;
				let step = this.toX > x ? offset : -offset;
				direction = this.toX > x ? 1 : 3;

				if (index === 2) {
					y = y - 30;
					this.ctx.lineTo(x, y);
					this.ctx.stroke();
				}
				repeat(x + step, y);
			}
		} else if (direction === 1) {
			if (this.toX >= x) {
				if (Math.abs(this.toX - x) > Math.abs(this.toY - y)) {
					obliqueY.call(this)
				} else {
					// 常规
					x1 = this.toX;
					y1 = y;
				}
				next();
			} else {
				let offset =
					index === 2 ? this.height / 2 + 30 : this.width + 60;
				offset = index <= 3 ? offset : 0;
				let step = this.toY > y ? offset : -offset;
				direction = this.toY > y ? 2 : 0;
				if (index === 2) {
					x = x + 30;
					this.ctx.lineTo(x, y);
					this.ctx.stroke();
				}
				repeat(x, y + step);
			}
		} else if (direction === 2) {
			if (this.toY >= y) {
				if (Math.abs(this.toY - y) > Math.abs(this.toX - x)) {
					obliqueX.call(this)
				} else {
					// 常规
					x1 = x;
					y1 = this.toY;
				}
				next();
			} else {
				let offset =
					index === 2 ? this.width / 2 + 30 : this.height + 60;
				offset = index <= 3 ? offset : 0;
				let step = this.toX > x ? offset : -offset;
				direction = this.toX > x ? 1 : 3;
				if (index === 2) {
					y = y + 30;
					this.ctx.lineTo(x, y);
					this.ctx.stroke();
				}
				repeat(x + step, y);
			}
		} else if (direction === 3) {
			if (this.toX <= x) {
				if (Math.abs(this.toX - x) > Math.abs(this.toY - y)) {
					obliqueY.call(this)
				} else {
					// 常规
					x1 = this.toX;
					y1 = y;
				}
				next();
			} else {
				let offset =
					index === 2 ? this.height / 2 + 30 : this.width + 60;
				offset = index <= 3 ? offset : 0;
				let step = this.toY > y ? offset : -offset;
				direction = this.toY > y ? 2 : 0;
				if (index === 2) {
					x = x - 30;
					this.ctx.lineTo(x, y);
					this.ctx.stroke();
				}
				repeat(x, y + step);
			}
		}
	}

	drawArrow(fromX, fromY, toX, toY) {
		// console.log("方向：", this.direction)
		const {
			theta = 30,
			headlen = 10,
			width = 2,
			color = "0f0",
		} = this.props;

		// 计算各角度和对应的P2,P3坐标
		var angle = (Math.atan2(fromY - toY, fromX - toX) * 180) / Math.PI,
			angle1 = ((angle + theta) * Math.PI) / 180,
			angle2 = ((angle - theta) * Math.PI) / 180,
			topX = headlen * Math.cos(angle1),
			topY = headlen * Math.sin(angle1),
			botX = headlen * Math.cos(angle2),
			botY = headlen * Math.sin(angle2);

		this.ctx.save();
		this.ctx.beginPath();

		var arrowX = fromX - topX,
			arrowY = fromY - topY;

		this.ctx.moveTo(arrowX, arrowY);
		this.ctx.moveTo(fromX, fromY);
		this.ctx.lineTo(toX, toY);
		arrowX = toX + topX;
		arrowY = toY + topY;
		this.ctx.moveTo(arrowX, arrowY);
		this.ctx.lineTo(toX, toY);
		arrowX = toX + botX;
		arrowY = toY + botY;
		this.ctx.lineTo(arrowX, arrowY);
		this.ctx.strokeStyle = color;
		this.ctx.lineWidth = width;
		this.ctx.stroke();
		// ctx.restore();
	}
}

export default DrawArrow;
